home *** CD-ROM | disk | FTP | other *** search
-
- /* Generated by Interface Builder */
-
- #import <math.h>
- #import <appkit/nextstd.h>
- #import "Car_main.h"
- #import "Car.h"
- #import "Wheels.h"
- #import "Cycle.h"
- #import "DataView.h"
- #import "AppDelegate.h"
- #import "Road.h"
- #import "Controller.h"
- #import "Transmission.h"
- #import "GasTank.h"
- #import "Battery.h"
-
- @implementation Car
-
- - init
- {
- [super init];
- car = self;
- return self;
- }
-
- - read:(NXTypedStream *)stream
- {
- [super read:stream];
- NXReadTypes(stream,"fffci",&dragCoefficient,&frontalArea,&mass,&plotAcceleration,&testMode);
- return self;
- }
-
- - write:(NXTypedStream *)stream
- {
- [super write:stream];
- NXWriteTypes(stream,"fffci",&dragCoefficient,&frontalArea,&mass,&plotAcceleration,&testMode);
- return self;
- }
-
- - (float)dragCoefficient
- {
- return dragCoefficient;
- }
-
- - setDragCoefficient:(float)aNumber
- {
- dragCoefficient = aNumber;
- return self;
- }
-
- - (float)frontalArea
- {
- return frontalArea;
- }
-
- - setFrontalArea:(float)aNumber
- {
- frontalArea = aNumber;
- return self;
- }
-
- - (float)mass
- {
- return mass;
- }
-
- - setMass:(float)aNumber
- {
- mass = aNumber;
- return self;
- }
-
- - setRoadForce:(float)aNumber
- {
- roadForce = aNumber;
- return self;
- }
-
- - (float)currentVelocity
- {
- return currentVelocity;
- }
-
- - (BOOL)plotAcceleration
- {
- return plotAcceleration;
- }
-
- - setPlotAcceleration:(BOOL)flag
- {
- plotAcceleration = flag;
- return self;
- }
-
- - (int)testMode;
- {
- return testMode;
- }
-
- - setTestMode:(int)mode
- {
- testMode = mode;
- return self;
- }
-
- - runSimulation:sender
- {
- float Mass;
- float totalMass;
- float CdA;
- float rho;
- float Cr;
- float aero;
- float rolling;
- float inertial;
- float velocity;
- float acceleration;
- float requiredAcceleration;
- double theta;
- float gradient;
- float power;
- struct plotData point;
-
- [cycle reset];
- [road reset];
- [battery getSetForRun];
- [gasTank getSetForRun];
-
- if ( plotAcceleration )
- {
- if ( !accelerationGraph )
- {
- accelerationGraph = [appDelegate newGraph];
- [[accelerationGraph window] setTitle:"Acceleration (m/s^2)"];
- }
- [[accelerationGraph window] orderFront:nil];
- }
- [[accelerationGraph data] empty];
-
- if ( 1 ) // There should be another option for this graph. Not implemented yet.
- {
- if ( !velocityGraph )
- {
- velocityGraph = [appDelegate newGraph];
- [[velocityGraph window] setTitle:"Velocity (m/s)"];
- }
- [[velocityGraph window] orderFront:nil];
- }
- [[velocityGraph data] empty];
-
- if ( 1 ) // There should be another option for this graph. Not implemented yet.
- {
- if ( !powerGraph )
- {
- powerGraph = [appDelegate newGraph];
- [[powerGraph window] setTitle:"Power (kW)"];
- }
- [[powerGraph window] orderFront:nil];
- }
- [[powerGraph data] empty];
-
- Mass = mass;
- Mass += [controller mass];
- Mass += [transmission mass];
- Mass += [engine mass];
- Mass += [gasTank mass];
- Mass += [motor mass];
- Mass += [battery mass];
- Mass += [wheel mass] * 4;
-
- CdA = dragCoefficient * frontalArea;
- rho = 94 * 28.97 / 8.3143 / 293; // air density in kg/m^3
- Cr = [wheel rollingResistance];
- energy = 0;
-
- /******************************************************************************************************************************
- * That was setup. Here's where the action really starts. *
- ******************************************************************************************************************************/
- if ( testMode == ARBITRARY )
- {
- while ( [cycle getNextVelocity:&velocity andAcceleration:&acceleration] )
- {
- totalMass = Mass + [gasTank fuelMass];
- velocity = velocity / 3.6; //conversion from km/h to m/s
- acceleration = acceleration / 3.6; //likewise
- point.x = [cycle lastTime];
- point.y = velocity;
- [velocityGraph addData:&point];
- point.y = acceleration;
- [accelerationGraph addData:&point];
-
- aero = CdA * rho * pow(velocity+[road windSpeed],2) / 2;
- rolling = totalMass * 9.807 * Cr;
- inertial = totalMass * acceleration;
-
- theta = atan([road slope]);
- gradient = 9.807 * totalMass * sin(theta);
-
- power = velocity * ( aero + rolling + inertial + gradient );
- point.y = power / 1000;
- [road advance:[cycle timeStep] atSpeed:velocity];
- energy += point.y * [cycle timeStep];
-
- [powerGraph addData:&point];
- }
- }
- else if ( testMode == LIMITED )
- {
- [cycle getNextVelocity:¤tVelocity andAcceleration:&acceleration];
- currentVelocity /= 3.6;
- point.x = [cycle lastTime];
- point.y = currentVelocity;
- [velocityGraph addData:&point];
-
- while ( [cycle getNextVelocity:&velocity andAcceleration:&acceleration] ) // Note: we don't use the accel returned here
- {
- totalMass = Mass + [gasTank fuelMass];
- velocity = velocity / 3.6; //conversion from km/h to m/s
- acceleration = ( velocity - currentVelocity ) / [cycle timeStep];
- requiredAcceleration = acceleration;
- point.x = [cycle lastTime];
-
- aero = CdA * rho * pow(currentVelocity+[road windSpeed],2) / 2;
- rolling = totalMass * 9.807 * Cr;
- inertial = totalMass * requiredAcceleration;
-
- theta = atan([road slope]);
- gradient = 9.807 * totalMass * sin(theta);
- [road advance:[cycle timeStep] atSpeed:currentVelocity];
-
- if ( currentVelocity == 0 )
- power = velocity * ( aero + rolling + inertial + gradient );
- else
- power = currentVelocity * ( aero + rolling + inertial + gradient ); // This is the required power in watts
-
- [controller powerRequired:power]; // We send a message to the controller, and the whole thing begins
-
- if ( (roadForce != 0) || (currentVelocity != 0) )
- inertial = roadForce - aero - rolling - gradient; // After the messages have run their course, we get a force
- else
- inertial = 0;
- acceleration = inertial / totalMass; // a = f/m
-
- if ( requiredAcceleration >= 0 ) // This is so we don't use up more power than we need.
- acceleration = MIN(acceleration,requiredAcceleration); // It's just to overcome a problem with standing starts.
- else if ( requiredAcceleration < 0 )
- acceleration = MAX(acceleration,requiredAcceleration);
-
- point.y = currentVelocity * ( acceleration * totalMass + aero + rolling + gradient ) / 1000;
- [powerGraph addData:&point];
-
- currentVelocity += acceleration * [cycle timeStep]; // Advance the velocity by this much
- currentVelocity = MAX(currentVelocity,0); // We never go backwards.
-
- point.y = currentVelocity;
- [velocityGraph addData:&point];
- point.y = acceleration;
- [accelerationGraph addData:&point];
- // fprintf(stderr,"%8f %8f %8f \n",aero,inertial,roadForce);
- }
- }
-
- [accelerationGraph drawLimits];
- [velocityGraph drawLimits];
- [powerGraph drawLimits];
-
- [[accelerationGraph window] display];
- [[velocityGraph window] display];
- [[powerGraph window] display];
-
- [appDelegate simulationEnded];
-
- [battery finishedRun];
- [gasTank finishedRun];
-
- return self;
- }
-
- - report:(NXStream *)stream
- {
- float Mass;
-
- Mass = mass;
- Mass += [controller mass];
- Mass += [transmission mass];
- Mass += [engine mass];
- Mass += [gasTank mass];
- Mass += [motor mass];
- Mass += [battery mass];
- Mass += [wheel mass] * 4;
- Mass += [gasTank fuelMass];
-
- NXPrintf(stream,"Car:\n");
- NXPrintf(stream," Total Mass:%fkg\n",Mass);
- NXPrintf(stream," Energy Used:%fkWh\n",energy/3600.0);
- return self;
- }
-
- @end
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-